﻿using AutoMapper;
using Furion;
using Furion.DataEncryption;
using Furion.DependencyInjection;
using Furion.LinqBuilder;
using Microsoft.EntityFrameworkCore;
using System.Security.Claims;
using XinGuanERP.Db;
using XinGuanERP.Models.Po.system;
using XinGuanERP.Models.Vo.system;
using XinGuanERP.Services.system.IServices;
using XinGuanERP.Utils;

namespace XinGuanERP.Services.system
{
    public class UserService : IUserService, ITransient
    {
        private readonly DefaultDbContext _defaultDbContext;

        public UserService(DefaultDbContext defaultDbContext)
        {
            _defaultDbContext = defaultDbContext;
        }

        public bool DeleteUser(string UserId)
        {
            var res = _defaultDbContext.Users.FirstOrDefault(t => t.Id == UserId);
            if (res != null)
            {
                _defaultDbContext.Users.Remove(res);
                return _defaultDbContext.SaveChanges() > 0;
            }
            else
            {
                return false;
            }
        }

        public UserVo GetUserByUserId(string userId)
        {
            var res = _defaultDbContext.Users.FirstOrDefault(u => u.Id == userId);
            var config = new MapperConfiguration(cfg => cfg.CreateMap<User, UserVo>()
                .ForMember(dest => dest.username, opt => opt.MapFrom(src => src.UserName))
                .ForMember(dest => dest.RoleId, opt => opt.MapFrom(src => src.Role!.Id))
                .ForMember(dest => dest.RoleName, opt => opt.MapFrom(src => src.Role!.RoleName))
                .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.Id))
                .AfterMap((src, des) => des.password = null));
            var mapper = config.CreateMapper();
            return mapper.Map<UserVo>(res);
        }

        public List<UserVo> GetUserWithList(string DeptId, string? userName, string? realName)
        {
            var res = new List<User>();
            if (!string.IsNullOrEmpty(DeptId))
            {
                var pdeptRes = _defaultDbContext.Depts
                    .Where(t => t.Id == DeptId).Select(t => t.ParentDept).FirstOrDefault();
                // 如果pdept是空的，是一级部门
                if (string.IsNullOrEmpty(pdeptRes))
                {
                    if (!userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = _defaultDbContext.Users.Include(user => user.Role)
                            .Where(u => _defaultDbContext.Depts.Where(d => d.ParentDept == DeptId)
                                    .Select(d => d.Id)
                                    .ToList()
                                .Contains(u.DeptId))
                            .Where(u => EF.Functions.Like(u.UserName!, "%" + userName + "%")).ToList();
                    }
                    if (!realName.IsNullOrEmpty() && userName.IsNullOrEmpty())
                    {
                        res = _defaultDbContext.Users.Include(user => user.Role)
                            .Where(u => _defaultDbContext.Depts.Where(d => d.ParentDept == DeptId)
                                    .Select(d => d.Id)
                                    .ToList()
                                .Contains(u.DeptId))
                            .Where(u => EF.Functions.Like(u.RealName!, "%" + realName + "%")).ToList();
                    }
                    if (!userName.IsNullOrEmpty() && !realName.IsNullOrEmpty())
                    {
                        res = _defaultDbContext.Users.Include(user => user.Role)
                            .Where(u => _defaultDbContext.Depts.Where(d => d.ParentDept == DeptId)
                                    .Select(d => d.Id)
                                    .ToList()
                                .Contains(u.DeptId))
                            .Where(u => EF.Functions.Like(u.UserName!, "%" + userName + "%"))
                            .Where(u => EF.Functions.Like(u.RealName!, "%" + realName + "%")).ToList();
                    }
                    if (userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = _defaultDbContext.Users.Include(user => user.Role)
                            .Where(u => _defaultDbContext.Depts.Where(d => d.ParentDept == DeptId)
                                    .Select(d => d.Id)
                                    .ToList()
                                .Contains(u.DeptId)).ToList();
                    }
                }
                else
                {
                    res = _defaultDbContext.Users
                        .Include(user => user.Role)
                        .Where(u => u.DeptId == DeptId).ToList();
                }
            }
            else
            {
                res = _defaultDbContext.Users.Include(user => user.Role).ToList();
            }

            var config = new MapperConfiguration(cfg => cfg.CreateMap<User, UserVo>()
                .ForMember(dest => dest.username, opt => opt.MapFrom(src => src.UserName))
                .ForMember(dest => dest.RoleId, opt => opt.MapFrom(src => src.Role!.Id))
                .ForMember(dest => dest.RoleName, opt => opt.MapFrom(src => src.Role!.RoleName))
                .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.Id)));
            var mapper = config.CreateMapper();
            return res.Select(user => mapper.Map<UserVo>(user)).ToList();
        }

        public PageResult<UserVo> GetUserWithPage(int page, int pageSize, string DeptId, string? userName, string? realName)
        {
            var res = new List<User>();
            var count = 0;
            if (!string.IsNullOrEmpty(DeptId))
            {
                var pdeptRes = _defaultDbContext.Depts
                    .Where(t => t.Id == DeptId).Select(t => t.ParentDept).FirstOrDefault();
                // 如果pdept是空的，是一级部门 一级部门查询
                if (string.IsNullOrEmpty(pdeptRes))
                {
                    var sql = _defaultDbContext.Users.Include(user => user.Role)
                            .Where(u => _defaultDbContext.Depts.Where(d => d.ParentDept == DeptId)
                                    .Select(d => d.Id)
                                    .ToList()
                                .Contains(u.DeptId))
                            .AsQueryable();
                    if (!userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%")).Count();
                    }
                    if (!realName.IsNullOrEmpty() && userName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                    }
                    if (!userName.IsNullOrEmpty() && !realName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                    }
                    if (userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = sql.Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Count();
                    }
                } // 二级部门查询
                else
                {
                    var sql = _defaultDbContext.Users
                        .Include(user => user.Role)
                        .Where(u => u.DeptId == DeptId).AsQueryable();
                    if (!userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%")).Count();
                    }
                    if (!realName.IsNullOrEmpty() && userName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                    }
                    if (!userName.IsNullOrEmpty() && !realName.IsNullOrEmpty())
                    {
                        res = sql
                            .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                            .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                        count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                            .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                    }
                    if (userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                    {
                        res = sql.ToList();
                        count = sql.Count();
                    }
                }
            }
            else
            {
                var sql = _defaultDbContext.Users.Include(user => user.Role).AsQueryable();
                if (userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                {
                    res = sql.ToList();
                    count = sql.Count();
                }
                if (!userName.IsNullOrEmpty() && realName.IsNullOrEmpty())
                {
                    res = sql
                        .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                        .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                    count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%")).Count();
                }
                if (!realName.IsNullOrEmpty() && userName.IsNullOrEmpty())
                {
                    res = sql
                        .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                        .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                    count = sql.Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                }
                if (!userName.IsNullOrEmpty() && !realName.IsNullOrEmpty())
                {
                    res = sql
                        .Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                        .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%"))
                        .Skip((page - 1) * pageSize).Take(pageSize).ToList();
                    count = sql.Where(u => EF.Functions.Like(u.UserName, "%" + userName + "%"))
                        .Where(u => EF.Functions.Like(u.RealName, "%" + realName + "%")).Count();
                }
            }

            List<UserVo> viewUsers = new();
            var config = new MapperConfiguration(cfg => cfg.CreateMap<User, UserVo>()
                .ForMember(dest => dest.username, opt => opt.MapFrom(src => src.UserName))
                .ForMember(dest => dest.RoleId, opt => opt.MapFrom(src => src.Role.Id))
                .ForMember(dest => dest.RoleName, opt => opt.MapFrom(src => src.Role.RoleName))
                .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.Id))
                .AfterMap((src, des) => des.password = null));
            var mapper = config.CreateMapper();
            foreach (var user in res)
            {
                viewUsers.Add(
                    mapper.Map<UserVo>(user)
                );
            }
            return new PageResult<UserVo>
            {
                Items = viewUsers,
                Total = count
            };
        }

        public bool ResetToDefaultPassword(string UserId)
        {
            var res = _defaultDbContext.Users.FirstOrDefault(t => t.Id == UserId);
            if (res != null)
            {
                res.UpdateTime = DateTime.Now;
                res.UpdateUserId = App.User?.FindFirstValue("UserId");
                res.UpdateUserName = App.User?.FindFirstValue("UserName");
                res.PassWord = MD5Encryption.Encrypt("123456");
                return _defaultDbContext.SaveChanges() > 0;
            }
            else
            {
                return false;
            }
        }

        public bool UpdateUser(UserVo viewUser)
        {
            var res = _defaultDbContext.Users.FirstOrDefault(x => x.Id == viewUser.UserId);
            var config = new MapperConfiguration(cfg => cfg.CreateMap<UserVo, User>()
                .ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.username))
                .BeforeMap((src, des) => src.UserId = Guid.NewGuid().ToString().Replace("-", "").ToUpper())
                .BeforeMap((src, des) => src.password = MD5Encryption.Encrypt("123456"))
                .BeforeMap((src, des) => des.CreateTime = DateTime.Now)
                .BeforeMap((src, des) => des.CreateUserId = App.User?.FindFirstValue("UserId"))
                .BeforeMap((src, des) => des.CreateUserName = App.User?.FindFirstValue("UserName")));
            var mapper = config.CreateMapper();
            if (res == null)
            {
                _defaultDbContext.Users.Add(
                mapper.Map<User>(viewUser)
                    );
            }
            else
            {
                res = new MapperConfiguration(cfg => cfg.CreateMap<UserVo, User>()
                    .BeforeMap((src, des) => src.password = des.PassWord)
                    .BeforeMap((src, des) => des.UpdateTime = DateTime.Now)
                    .BeforeMap((src, des) => des.UpdateUserId = App.User?.FindFirstValue("UserId"))
                    .BeforeMap((src, des) => des.UpdateUserName = App.User?.FindFirstValue("UserName")))
                    .CreateMapper().Map(viewUser, res);
            }
            return _defaultDbContext.SaveChanges() > 0;
        }
    }
}
